package com.samtech.spring.components;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.PartialViewContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.PhaseId;
import javax.faces.model.DataModel;
import javax.faces.model.DataModelEvent;
import javax.faces.model.DataModelListener;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.primefaces.component.datagrid.DataGrid;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.UploadedFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.samtech.common.domain.PagingAndSorting;
import com.samtech.common.service.CommonQueryService;
import com.samtech.domain.EtAirport;
import com.samtech.primefaces.service.EtAirportService;



@Component("manageEtairports")
@Scope("request")
public class ManageEtairports implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -5998975540686588305L;

	private List<EtAirport> airports;
	
	private EtAirportService etAirportService;
	private boolean renderTbl;
	
	private String countryCode;
	private Integer pageSize=10;
	//@Bean()
	private CommonQueryService queryService;
	
	DataModel<?> dataModel;
	DataModel<?> gridModel;
	private EtAirport etairport;
	private EtAirport editEtairport;

	String phaseid;

	public ManageEtairports() {}
	public EtAirport getEditEtairport() {
		if(editEtairport==null){
			return new EtAirport();
		}
		return editEtairport;
	}
	
	
	public void setEditEtairport(EtAirport editEtairport) {
		this.editEtairport = editEtairport;
	}
	
	
	public String getCountryCode() {
		FacesContext cxt = FacesContext.getCurrentInstance();
		Map<String, Object> sessionMap = cxt.getExternalContext().getSessionMap();
		
		String key = this.getClass().getSimpleName()+"_countryCode";
		if(sessionMap.containsKey(key))
			return (String)sessionMap.get(key);
		return countryCode;
	}
	//@Scope(value="session")
	public void setCountryCode(String countryCode) {
		this.countryCode = countryCode;
	}
	

	public boolean isRenderTbl() {
		if(!renderTbl){
			FacesContext cxt = FacesContext.getCurrentInstance();
			Map<String, Object> sessionMap = cxt.getExternalContext().getSessionMap();
			Object object = sessionMap.get(this.getClass().getSimpleName()+"_renderTbl");
			if(object!=null)return (Boolean)object;
			if(cxt.getExternalContext().getRequestParameterMap().containsKey(PartialViewContext.PARTIAL_EXECUTE_PARAM_NAME)){
			    String ss = cxt.getExternalContext().getRequestParameterMap().get(PartialViewContext.PARTIAL_EXECUTE_PARAM_NAME);
			    if(ss.indexOf("etairports")>=0)return true;
			}
		}
		return renderTbl;
	}


	public void setRenderTbl(boolean renderTbl) {
		this.renderTbl = renderTbl;
	}


	public Integer getPageSize() {
		return pageSize;
	}

	public void setPageSize(Integer pageSize) {
		this.pageSize = pageSize;
	}

	@Autowired
	public void setEtAirportService(EtAirportService etAirportService) {
		this.etAirportService = etAirportService;
	}
	
	@Autowired
	public void setCommonQueryService(CommonQueryService queryService) {
		this.queryService = queryService;
	}

	
	public List<EtAirport> getEtairports() {
		return airports;
	}
	public void setEtairports(List<EtAirport> movies) {
		this.airports = movies;
	}
	
	
	
	public EtAirport getEtAirport() {
		return etairport;
	}

	public void setEtAirport(EtAirport et) {
		this.etairport = et;
	}
	
	
	
	public DataModel<?> getDataModel(){
	
		if(dataModel==null)
			dataModel=genDataModel();
		return dataModel;
	}
	
	@SuppressWarnings({ "unchecked" })
	private DataModel<?> genDataModel(){
		//int totalRows=0;
		Map<String, Object> param=new HashMap<String, Object>();
		String c = getCountryCode();
		String sql="select o from "+EtAirport.class.getName()+ " as o ";
		if(StringUtils.isNotBlank(c)){
			sql+=" where o.barcode=:p_cname ";
			param.put("p_cname", c.trim());
		}
		PagingAndSorting pg=new PagingAndSorting();
		
		//List lst = queryService.query(EtAirport.class, sql, param, pg);
		/*Object o = lst.get(0);
		totalRows=((Number)o).intValue();*/
		//ListDataModel model = new ListDataModel(lst);
		LazyDataModel<EtAirport> model= new LazyDataModel<EtAirport>(){
		    private int rowCount=-1;
		    @Override
		    public void setRowIndex(int rowIndex) {
		        if(this.getPageSize()>0)
		        super.setRowIndex(rowIndex);
		    }
		    @Override
		    public int getRowCount() {
		        if(rowCount==-1){
		            rowCount=initRowCount();
		        }
		        return rowCount;
		        //return super.getRowCount();
		    }
		    private int initRowCount(){
		        String c = getCountryCode();
		        Map<String, Object> param=new HashMap<String, Object>();
                String sql="select count(o.airportCode) from "+EtAirport.class.getName()+ " as o ";
                if(StringUtils.isNotBlank(c)){
                    sql+=" where o.barcode=:p_cname ";
                    param.put("p_cname", c.trim());
                }
                
                PagingAndSorting pg=new PagingAndSorting();
              
                pg.setAlias("o");
                List<Long> lst = queryService.query(Long.class, sql, param, pg);
                return (int)lst.get(0).intValue();
		       
		    }
			@Override
			public List<EtAirport> load(int first, int pageSize,
					String sortField, boolean sortOrder,
					Map<String, String> filters) {
				Map<String, Object> param=new HashMap<String, Object>();
				String c = getCountryCode();
				String sql="select o from "+EtAirport.class.getName()+ " as o ";
				if(StringUtils.isNotBlank(c)){
					sql+=" where o.barcode=:p_cname ";
					param.put("p_cname", c.trim());
				}
				
				PagingAndSorting pg=new PagingAndSorting();
				pg.setStart(first);
				pg.setEnd(first+pageSize);
				pg.setAlias("o");
				List lst = queryService.query(EtAirport.class, sql, param, pg);
				return lst;
			}
		};
		
		return model;
	}
	public void postview(ComponentSystemEvent event){
		FacesContext cxt = FacesContext.getCurrentInstance();
		PhaseId cuPhaseId = cxt.getCurrentPhaseId();
		UIComponent component = event.getComponent();
		if(cuPhaseId!=null){
			if(phaseid==null)phaseid=cuPhaseId.toString();
			else if(phaseid.equals(cuPhaseId.toString())){
				return;
			}else phaseid=cuPhaseId.toString();
		}
		System.out.println("event comp=" +component.getClientId());
		System.out.println(cuPhaseId.toString()+" @" +new Date());
		gridModel=null;
	}
	public DataModel<?> getGridModel(){
		FacesContext cxt = FacesContext.getCurrentInstance();
		PhaseId cuPhaseId = cxt.getCurrentPhaseId();
		System.out.println("getGridModel");
		System.out.println(cuPhaseId.toString()+" @" +new Date());
		 if(gridModel==null)
			gridModel=genGridModel();
		
		return gridModel;
	}
	
	public DataModel<?> genGridModel() {
		FacesContext cxt = FacesContext.getCurrentInstance();
		UIComponent curComp = UIComponent.getCurrentComponent(cxt);
		UIViewRoot viewRoot = cxt.getViewRoot();
		UIComponent g = viewRoot.findComponent("etairportgrids");
		// UIComponent g = curComp.findComponent("etairportgrids");
		if(g==null){
			g = curComp.findComponent("etairportgrids");
			if(g==null){
				UIComponent parent = curComp.getParent();
				if(parent!=null){
					UIComponent p = parent.getParent();
					if(p!=null)parent=p;
					g = curComp.findComponent("etairportgrids");
				}
				
			}
			if(g==null){
				System.out.println("not found grid datamodel is null");
				return null;
			}
		}
		DataGrid grid = (DataGrid) g;
		
		int columns = grid.getColumns();
		int first = grid.getFirst();
		int pageSize = grid.getRows();
		int page = grid.getPage();
		System.out.println("cols=" + columns + ";first=" + first + ";rows="
				+ pageSize + ";page=" + page);
		Map<String, Object> param = new HashMap<String, Object>();
		String c = getCountryCode();

		String sql = "select o from " + EtAirport.class.getName() + " as o ";
		if (StringUtils.isNotBlank(c)) {
			sql += " where o.barcode=:p_cname ";
			param.put("p_cname", c.trim());
		}
		PagingAndSorting pg = new PagingAndSorting();
		pg.setStart(first);
		pg.setEnd(first + pageSize);

		List lst = queryService.query(EtAirport.class, sql, param, pg);
		sql = "select count(o.airportCode) from " + EtAirport.class.getName()
				+ " as o ";
		if (StringUtils.isNotBlank(c)) {
			sql += " where o.barcode=:p_cname ";
			param.put("p_cname", c.trim());
		}
		pg = new PagingAndSorting();

		List lst1 = queryService.query(EtAirport.class, sql, param, pg);
		Object object = lst1.get(0);
		int totalrows = ((Number) object).intValue();
		return new AirportDataModel(first, pageSize, page, totalrows, lst);

	}
	
	public static class AirportDataModel extends DataModel<EtAirport>{
		private int _first=-1,_rowCount=-1,_pageSize=0,_page=0;
		private List<EtAirport> _lst=null;
		
		private int idx;
		
		public AirportDataModel(int first,int pageSize,int page,int totalCount,List<EtAirport> lists){
			_first=first;
			_lst=lists;
			_pageSize=pageSize;
			_page=page;
			_rowCount=totalCount;
		}
		
		@Override
		public int getRowCount() {
			return _rowCount;
			
		}

		@Override
		public EtAirport getRowData() {
			if (this._lst == null)
				       return null;
			if (!(isRowAvailable())) {
				      throw new IllegalArgumentException("RowAvailable fail");
				  }
			int p=0;
			if(_page>0)
			p=_page-1;	
			if(idx<0)return null;
			int k=idx-_first;
			return _lst.get(k);
	
		}

		@Override
		public int getRowIndex() {
	
			return idx;
		}

		@Override
		public Object getWrappedData() {
			return _lst;
			
		}

		@Override
		public boolean isRowAvailable() {
			if (this._lst == null) {
				       return false;
				     }
			//return true;
			if(idx==-1)return false;
			
			int k=idx-_first;
			//System.out.println("idx-_first="+idx+"-"+_first+";list size"+_lst.size());
			return (k>=0  && (k < this._lst.size()));
		}

		@Override
		public void setRowIndex(int rowIndex) {

			     if (rowIndex < -1) {
			      throw new IllegalArgumentException();
		   }
			    int old = this.idx;
			   this.idx = rowIndex;
			    if (this._lst == null) {
			       return;
			    }
			  DataModelListener[] listeners = getDataModelListeners();
			     if ((old != this.idx) && (listeners != null)) {
			     Object rowData = null;
			       if (isRowAvailable()) {
			        rowData = getRowData();
			       }
			      DataModelEvent event = new DataModelEvent(this, this.idx, rowData);
			
			     int n = listeners.length;
			      for (int i = 0; i < n; ++i)
			        if (null != listeners[i])
			          listeners[i].rowSelected(event);
			     }
			  
		}

		
	
	 public void setWrappedData(Object data)
		  {
		   if (data == null) {
		      this._lst = null;
		      setRowIndex(-1);
		   } else {
		      this._lst = ((List)data);
		     this.idx = -1;
		     setRowIndex(0);
		     }
		 }
		
	}
	
	public void search(ActionEvent actionEvent) {
		//airports = etAirportService.findAll();
		
		FacesContext cxt = FacesContext.getCurrentInstance();
		ExternalContext externalContext = cxt.getExternalContext();
		Map<String, Object> sessionMap = externalContext.getSessionMap();
		sessionMap.put(this.getClass().getSimpleName()+"_countryCode", this.countryCode);
		//sessionMap.put(this.getClass().getSimpleName()+"_renderTbl", Boolean.TRUE);
		this.renderTbl=true;
		dataModel=null;
		gridModel=null;
		//UIComponent.
		//externalContext.get
	}
	
	public void showView(ActionEvent actionEvent ){
		FacesContext cxt = FacesContext.getCurrentInstance();
		ExternalContext externalContext = cxt.getExternalContext();
		Map<String, String> params = externalContext.getRequestParameterMap();
		Map<String, Object> requestMap = externalContext.getRequestMap();
		String object = params.get("aircode");
		System.out.println("aircode="+object);
		if(object!=null && object.length()>0){
			EtAirport et = this.etAirportService.findById(object);
			this.setEtAirport(et);
			this.setEditEtairport(et);
		}
	}
	
	public void saveEtairport(ActionEvent actionEvent){
		FacesContext cxt = FacesContext.getCurrentInstance();
		List<FacesMessage> messageList = cxt.getMessageList();
		StringBuffer buf=new StringBuffer(30);
		if(messageList!=null && !messageList.isEmpty()){
			for (FacesMessage facesMessage : messageList) {
				Severity severity = facesMessage.getSeverity();
				buf.append("summary=").append(facesMessage.getSummary());
				buf.append(";detail=").append(facesMessage.getDetail());
				buf.append(";severity="+severity!=null?severity.toString():"").append("\n");
			}
			System.out.println(buf.toString());
		}
		editEtairport.setOpDate(new Date());
		editEtairport.setOpId("admin");
		etAirportService.update(editEtairport);
		this.dataModel=null;
	}
	
	public void handleUpLoad(FileUploadEvent uploadEvent){
		UploadedFile file = uploadEvent.getFile();
		if(file!=null){
			String fileName = file.getFileName();
			byte[] contents = file.getContents();
			InputStream inputStream=new ByteArrayInputStream(contents);
			poiupload(inputStream);
		}
	}
		
	private void poiupload(InputStream inputStream) {
		int counter=0;
		int m=0;
		try {
			//POIFSFileSystem pofs = new POIFSFileSystem(file.getContents());
			HSSFWorkbook workbook = new HSSFWorkbook(inputStream,false);
			int s_idx = workbook.getActiveSheetIndex();
			HSSFSheet sheet = workbook.getSheetAt(s_idx);
			int row_index=8000;
			int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
			boolean b=true;
			int emptys=0;
			Map<String,EtAirport> map=new HashMap<String,EtAirport>(20);
			while(b){
				if(map.size()>90){
					Collection<EtAirport> values = map.values();
					EtAirport[] array =new EtAirport[values.size()];
					values.toArray(array);
					this.etAirportService.batchCreate(array);
					map.clear();
				}
				counter++;
				if(counter>100){
					m++;
					System.out.println("counter="+counter+";m="+m);
					try {
						Thread.sleep(counter*(3+m));
						counter=0;
					} catch (InterruptedException e) {
						counter=0;
						e.printStackTrace();
					}
				}
				HSSFRow row = sheet.getRow(row_index++);
				if(row==null)
					emptys++;
				else{
					HSSFCell cell = row.getCell(0);
					String code = cell.getRichStringCellValue().getString();
					cell = row.getCell(1);
					String citycode = cell.getRichStringCellValue().getString();
					cell = row.getCell(2);
					String en_name = cell.getRichStringCellValue().getString();
					cell = row.getCell(3);
					String cn_name = cell.getRichStringCellValue().getString();
					cell = row.getCell(4);
					String countrycode = cell.getRichStringCellValue().getString();
					cell = row.getCell(5);
					String interflag = cell.getRichStringCellValue().getString();
					EtAirport entity = this.etAirportService.findById(code.trim());
					if(entity==null){
						EtAirport port = new EtAirport(code.trim(), "sys", new Date());
						port.setAirportChBrief(cn_name);
						port.setAirportEnBrief(en_name);
						port.setBarcode(countrycode);
						port.setCityCode(citycode);
						port.setInterFlag(new Character(interflag.charAt(0)));
						map.put(code.trim(), port);
						//this.etAirportService.createNew(port);
						
					}else{
						if(entity.getInterFlag()==null && interflag!=null){
							entity.setInterFlag(new Character(interflag.charAt(0)));
							etAirportService.update(entity);
						}
					}
				}
				if(emptys>1)b=false;
				if(row_index>=physicalNumberOfRows)b=false;
			}
			if(map.size()>0){
				Collection<EtAirport> values = map.values();
				EtAirport[] array =new EtAirport[values.size()];
				values.toArray(array);
				this.etAirportService.batchCreate(array);
				map.clear();
			}
		} catch (IOException e) {
			System.out.println("counter="+counter+";m="+m);
			e.printStackTrace();
		}
	}
}